package com.hzgj.soa.spring.schema;

import com.google.common.collect.Maps;
import com.hzgj.bcl.soa.api.IdempotentIdGen;
import com.hzgj.bcl.soa.api.IdempotentProcessor;
import com.hzgj.bcl.soa.config.MethodDef;
import com.hzgj.bcl.util.lang.StrKit;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;

import java.util.List;
import java.util.Map;

/**
 * Created by warning on 2016/10/27.
 */
public class ElementParser {

    public static Map<String, MethodDef> parserMethod(Element element, BeanDefinition beanDefinition) {
        List<Element> methodElements = DomUtils.getChildElementsByTagName(element, "method");
        Map<String, MethodDef> result = null;
        if (methodElements != null) {
            result = Maps.newHashMap();
            for (Element ele : methodElements) {
                MethodDef methodDef = new MethodDef();
                String name = ele.getAttribute("name");
                if (StrKit.isBlank(name)) {
                    throw new RuntimeException("Element of method name must be exist.");
                }
                methodDef.setName(name);
                String idempotentIdGen = ele.getAttribute("idempotentIdGen");
                Class<IdempotentIdGen> clazz = null;
                if (StrKit.notBlank(idempotentIdGen)) {
                    try {
                        clazz = (Class<IdempotentIdGen>) Thread.currentThread().getContextClassLoader().loadClass(idempotentIdGen);
                    } catch (ClassNotFoundException e) {
                        throw new RuntimeException(e);
                    }
                }
                methodDef.setIdempotentIdGenClass(clazz);

                String idempotentProcessor = ele.getAttribute("idempotentProcessor");
                Class<IdempotentProcessor> processorClass = null;
                if (StrKit.notBlank(idempotentProcessor)) {
                    try {
                        processorClass = (Class<IdempotentProcessor>) Thread.currentThread().getContextClassLoader().loadClass(idempotentProcessor);
                    } catch (ClassNotFoundException e) {
                        throw new RuntimeException(e);
                    }
                }
                methodDef.setIdempotentProcessorClass(processorClass);
                Integer connectTimeout = getMethodIntValue(beanDefinition, ele, "connectTimeoutInMills");
                if (connectTimeout != null) {
                    methodDef.setConnectTimeoutInMills(connectTimeout);
                }
                Integer requestTimeout = getMethodIntValue(beanDefinition, ele, "requestTimeoutInMills");
                if (requestTimeout != null) {
                    methodDef.setRequestTimeoutInMills(requestTimeout);
                }
                Integer retries = getMethodIntValue(beanDefinition, ele, "retries");
                if (retries != null) {
                    methodDef.setRetries(retries);
                }
                Integer msBeforeRetry = getMethodIntValue(beanDefinition, ele, "msBeforeRetry");
                if (msBeforeRetry != null) {
                    methodDef.setMsBeforeRetry(msBeforeRetry);
                }
                result.put(name, methodDef);
            }
        }
        return result;
    }

    private static Integer getMethodIntValue(BeanDefinition beanDefinition, Element ele, String property) {
        String ele_value = ele.getAttribute(property);
        if (StrKit.notBlank(ele_value)) {
            return Integer.parseInt(ele_value);
        } else {
            PropertyValue propertyValue = beanDefinition.getPropertyValues().getPropertyValue(property);
            if (propertyValue != null) {
                return (Integer) propertyValue.getValue();
            }
        }
        return null;
    }
}
